using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using SpoonCore.Tools;

namespace UDPPerformance
{
	class Program
	{
		private static readonly Random _rand = new Random();
		private static readonly BlockingRingBuffer<byte[]> _queue = new BlockingRingBuffer<byte[]>(100);
		private static readonly List<Thread> _reader = new List<Thread>();
		private static readonly List<Thread> _writer = new List<Thread>();
		private static bool _running = true;
		private static Socket socket;

		static void Main()
		{
			for (int x = 0; x < 1; x++)
			{
				Thread thread = new Thread(Write);
				thread.Name = "Write" + x;
				thread.Start();
			}
			for (int x = 0; x < 2; x++)
			{
				Thread thread = new Thread(Read);
				thread.Name = "Read" + x;
				thread.Start();
			}

			Console.ReadLine();
			_running = false;

			foreach (Thread thread in _writer)
			{
				EndThread(thread);
			}
			foreach (Thread thread in _reader)
			{
				EndThread(thread);
			}
		}

		private static void EndThread(Thread thread)
		{
			thread.Abort();
			thread.Interrupt();
			thread.Join();
		}

		private static void Read()
		{
			socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
			IPEndPoint endpoint = new IPEndPoint(IPAddress.Parse("192.168.0.3"), 1234);
			int count = 0;

			while(_running)
			{
				byte[] data = _queue.Dequeue();
				socket.SendTo(data, endpoint);
				count += data.Length;

				if (!_running) break;
			}
		}

		private static void Write()
		{
			RijndaelManaged ri = new RijndaelManaged();
			ri.GenerateKey();
			ri.GenerateIV();
			ICryptoTransform transformer = ri.CreateDecryptor();

			for (int x = 0; x < 1000000; x++)
			{
				byte[] data = new byte[64*16];
				byte[] buffer = new byte[data.Length];
				_rand.NextBytes(data);
				
				//transformer.TransformBlock(data, 0, data.Length, buffer, 0);
				_queue.Enqueue(buffer);

				if (!_running) break;
			}
		}
	}
}
